"""
http请求的封装
Powered By cc
2020/04/04
"""


from urllib.parse import quote

import jsonpath
import requests
import json


class HTTPKeyWord():
    """
    封装的http请求的关键字类
    Powered By cc
    2020/04/04
    """

    def __init__(self,excelWrite):
        """

        :param excelWrite: WriteExcel的实例
        """


        #创建session会话，使用session会话来进行发包
        self.session = requests.session()
        #url的地址，初始化值为空字符
        self.url = ''
        #返回的结果
        self.result = None

        #返回结果是json使用json的字典存储
        self.result_json = None
        #存储传递的参数
        self.saveparams = {}
        #要写入的第几行
        self.__line = 0
        self.write = excelWrite


    def setUrl(self,url):
        """
        设定项目的初始url地址
        :param url:
        :return:成功
        """
        #对于参数url空的处理
        if url is None or url =='':
            url = ''
        self.url = url
        self.write.writeCell(self.__line,10,'pass')
        return True
    def setLine(self,line):
        """
        设置要在第几行写入excel
        :param line:
        :return:
        """

        self.__line = int(line)

    def postData(self, path, params):
        """
        post的请求，data使用字典形式传参对应的urlencoded形式的参数
        :param path:接口的路径
        :param params:字典形式的接口参数
        :return:返回成功或者失败
        """
        #路径是空或者空字符串直接返回失败
        if path is None or path == "":
            return False
        #参数是空或者空字符给与None处理
        if params is None or params=='':
            params = None
        # params是字符串才进行处理
        if isinstance(params, str):
            #参数传递的作用
            params= self.__useSaveParms(params)
            #将urlencoded形式的参数进行转成字典
            params = self.__getData(params)
        #判断path是路径还是url地址
        if not path.startswith('http'):
            path = self.url + '/' + path
        #使用session发包
        self.result = self.session.post(path,data=params)
        try:
            #如果返回的是json字符串处理成字典，不是self.result_json还是None
            self.result_json = json.loads(self.result.text)
        except Exception as e:
            self.result_json = None
        self.write.writeCell(self.__line,11,str(self.result.text))

        return True


    def postJson(self,path,params):
        """
        josn格式的请求参数的post请求对应application/json
        :param path:接口路径
        :param params:字典形式的参数
        :return:成功或者失败
        """
        # 路径是空或者空字符串直接返回失败
        if path is None or path == "":
            return False
        # 参数是空或者空字符给与None处理
        if params is None or params == '':
            params = None

        #params是字符串才进行处理
        if isinstance(params,str):
            # 将json字符串转换成字典
            params = self.__useSaveParms(params)
            if params.startswith('{') and params.endswith('}'):
                pass
            #如果是urlencoded的进行转换成字典
            elif params.find('=') and params.find('&'):
                params = self.__getData(params)
                params = json.dumps(params)
            else:
                #两者都不是进行None处理
                params =None
        # 判断path是路径还是url地址
        if not path.startswith('http'):
            path = self.url + '/' + path

        self.result = self.session.post(path,json=params)
        try:
            #如果返回的是json字符串处理成字典，不是self.result_json还是None
            self.result_json = json.loads(self.result.text)
        except Exception as e:
            self.result_json = None
        self.write.writeCell(self.__line,11,str(self.result.text))

        return True




    def get(self,path,params):
        """
        get请求
        :param path: 接口路径
        :param params: urlencoded的参数形式如：id=1&user=cc
        :return:
        """
        #参数的空处理
        if params is None or params == '':
            params=None
        #接口路径的空处理
        if path is None or path =='':
            return False
        if not path.startswith('http'):
            path = self.url +'/' +path
        params = self.__useSaveParms(params)
        self.result = self.session.get(path+'?'+params)
        try:
            self.result_json = json.loads(self.result.text)
        except Exception as e:
            self.result_json = None
        self.write.writeCell(self.__line,11,str(self.result.text))
        return True

    def addHeader(self,key,vaule):
        """
        给header中添加键值对
        :param key:
        :param vaule:
        :return: 返回成功或者失败
        """
        if key is None or key =='':
            self.write.writeCell(self.__line,10,'fail')
            return False
        vaule = self.__useSaveParms(vaule)
        self.session.headers[key] = vaule
        self.write.writeCell(self.__line, 10, 'pass')
        self.write.writeCell(self.__line, 11, '添加成功'+vaule)
        return True

    def removeHeader(self,key):
        """
        取消header中的某个值
        :param key:去除掉header中的键
        :return:成功或者失败
        """
        if key is None or key =='':
            self.write.writeCell(self.__line, 10, 'fail')
            return False
        try:
            self.session.headers.pop(key)
        except Exception as e:
            self.write.writeCell(self.__line, 10, 'fail')
            self.write.writeCell(self.__line, 11, '删除' + key + '失败')
            return False
        self.write.writeCell(self.__line,10,'pass')
        self.write.writeCell(self.__line,11,'删除'+key+'成功')

        return True

    def saveJson(self,key,jsonPath):
        """
        通过jsonpath来提取需要存储的参数，并存储到self.saveparams字典中实现参数传递
        :param jsonsPath: jsonpath
        :param key: 保存键的值
        :return:成功或者失败
        """
        #如果jsonPath是空或者空字符直接返回错误
        if jsonPath is None or jsonPath =='':
            self.write.writeCell(self.__line,10,'fail')
            self.write.writeCell(self.__line, 11, 'jsonPath是空的')
            self.saveparams[key] = None
            return False
        #如果jsonPath不是以$开的也是返回错误
        if not jsonPath.startswith('$'):
            self.write.writeCell(self.__line, 10, 'fail')
            self.write.writeCell(self.__line, 11, 'jsonPath不是以$开头')
            self.saveparams[key] = None
            return False
        #如果result_josn是None也返回错误
        if self.result_json is None:
            self.write.writeCell(self.__line, 10, 'fail')
            self.write.writeCell(self.__line, 11, '返回结果不是json字符串')
            self.saveparams[key] =None
            return False
        try:
            self.saveparams[key] = jsonpath.jsonpath(self.result_json,jsonPath)[0]
            self.write.writeCell(self.__line, 10, 'pass')
            self.write.writeCell(self.__line, 11, 'key为'+key+'value是'+jsonpath.jsonpath(self.result_json,jsonPath)[0])
            return True
        except Exception as e:
            self.write.writeCell(self.__line, 10, 'fail')
            self.write.writeCell(self.__line, 11, 'jsonPath路径不对')
            return False

    def assertEqualJson(self,jsonPath,expValue):
        """
        通过jsonpath进行断言
        :param jsonPath:
        :param expValue:期望的结果
        :return:
        """
        if self.result_json is None :
            self.write.writeCell(self.__line,10,'fail')
            self.write.writeCell(self.__line,11,'返回结果不是json字符串')
            return False
        value = jsonpath.jsonpath(self.result_json,jsonPath)[0]
        if value:
            if str(value)== str(expValue):
                self.write.writeCell(self.__line,10,'pass')
            else:
                self.write.writeCell(self.__line, 10,'fail')
        else:
            self.write.writeCell(self.__line, 10, 'fail')
            self.write.writeCell(self.__line, 11, 'jsonpath编写不正确')
        return True

    def assertContains(self,expValue):
        """
        通过返回结果包含进行判断
        :param expValue:
        :return:
        """
        if expValue is None or expValue =='':
            self.write.writeCell(self.__line, 10, 'fail')
            self.write.writeCell(self.__line, 11, '期望结果不能为空')
            return False
        if expValue in self.result.text:
            self.write.writeCell(self.__line, 10, 'pass')
        else:
            self.write.writeCell(self.__line, 10, 'fail')



    def __useSaveParms(self,params):
        """
        将params中的{内容}转换成self.saveparams字典中存在对应键的值
        做到了参数的传递
        :param params:
        :return: 替换后的params
        """
        if params is None or params == '':
            return None
        for key in self.saveparams.keys():
            params = params.replace('{'+key+'}',self.saveparams[key])
        return params



    def __getData(self,params):
        """
        将urlencoded形式的参数转换成字典
        :param params:urlencoded的参数形式如：id=1&uesr=cc
        :return:空或者解析成功的字典
        """
        #对于参数空处理,返回None
        if params is None or params =='':
            return None
        dict1= {}
        #通过&符号进行分割
        for items in params.split('&'):
            #进行keyvalue成对处理
            if items[-1]=='=':
                dict1[quote(items.split('=')[0])] = ''
            else:
                dict1[quote(items.split('=')[0])] =quote(items.split('=')[-1])
        return dict1











if __name__ == '__main__':
    # http = HTTPKeyWord()
    #
    # http.setUrl('http://testingedu.com.cn:8081/inter/HTTP')
    # http.postDota('auth','')
    # http.seveJson('token','$.token')
    # print(http.saveparams)
    # http.addHeader('token','{token}')
    # print(http.session.headers['token'])
    pass






